package com.smart.common.transfer;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.smart.mapper.TransferMapper;
import com.smart.model.domain.ExcelDO;
import com.smart.model.domain.ManageUserRegistrationDO;
import com.smart.model.domain.ProjectDO;
import com.smart.model.domain.UnitDO;
import com.smart.service.ManageUserRegistrationService;
import com.smart.service.UnitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author macbook
 */
@Slf4j
@Component
public class UnitTransfer {

    @Autowired
    private TransferMapper transferMapper;
    @Autowired
    private UnitService unitService;
    @Autowired
    private ManageUserRegistrationService manageUserRegistrationService;

    /**
     * 单位数据迁移
     * @param oldId 老项目id
     * @param projectDO 新项目do
     */
    public void transferUnit(Long oldId, ProjectDO projectDO) {
        // 建设单位迁移
        List<ExcelDO> unitList = transferMapper.queryExcelUnitByProjectId(oldId);
        if (CollectionUtils.isEmpty(unitList)) {
            return;
        }
        List<UnitDO> entityList = buildUnitList(unitList, projectDO);
        // 新老建设单位id关联关系 key=老项目建设单位id，value= {left: 新项目建设单位id, right:单位性质}
        Map<Long, Pair<Long, String>> unitRelationMapping = new HashMap<>();
        for (UnitDO unitDO : entityList) {
            unitService.save(unitDO);
            unitRelationMapping.put(unitDO.getOldUnitId(), Pair.of(unitDO.getId(), unitDO.getUnitType()));
        }

        // 项目人员迁移
        transferProjectPerson(oldId, projectDO, unitRelationMapping);
    }

    public void transferProjectPerson(Long oldId, ProjectDO projectDO, Map<Long, Pair<Long, String>> unitRelationMapping) {
        List<ExcelDO> personList = transferMapper.queryExcelLastByOldProjectId(oldId);
        if (CollectionUtils.isEmpty(personList)) {
            return;
        }

        personList = personList.stream().filter(distinctByKey(ExcelDO::getIdNumber)).collect(Collectors.toList());
        List<ManageUserRegistrationDO> registrationList = buildManageUserRegistrationList(personList, projectDO, unitRelationMapping);
        manageUserRegistrationService.saveBatch(registrationList);
    }

    private List<ManageUserRegistrationDO> buildManageUserRegistrationList(List<ExcelDO> personList, ProjectDO projectDO, Map<Long, Pair<Long, String>> unitRelationMapping) {
        List<ManageUserRegistrationDO> manageUserRegistrationDOList = Lists.newArrayList();
        for (ExcelDO excelDO : personList) {
            ManageUserRegistrationDO registration = new ManageUserRegistrationDO();
            registration.setProjectId(projectDO.getId());
            if (excelDO.getUnitTypeId() == 3L) {
                registration.setUnitId(null);//总包单位的unitId保持为空
                registration.setUnitProperty("ZONGBAO_UNIT");
            } else {
                Pair<Long, String> longStringPair = unitRelationMapping.get(excelDO.getUnitTypeId());
                if (longStringPair == null) {
                    log.info("忽略人员信息");
                    continue;
                }
                registration.setUnitId(longStringPair.getLeft());
                registration.setUnitProperty(longStringPair.getRight());
            }

            registration.setUserName(excelDO.getName());
            registration.setAddress(projectDO.getAddress());
            registration.setCardType("1");//默认所有证件类型为身份证
            registration.setIdCard(excelDO.getIdNumber());
            registration.setUserPhone(excelDO.getPhone());
            registration.setJobType(covertJobType(excelDO.getPersonJobId()));
            registration.setInoculateNumber(excelDO.getVaccineNum());

            registration.setLeaveOrNot(0);//默认离场
            if (excelDO.getInDate() != null) {
                registration.setLeaveOrNot(1);//在场
                registration.setEntranceTime(excelDO.getInDate());
            }
            if (excelDO.getInDate() != null && excelDO.getOutDate() != null && DateUtil.compare(excelDO.getInDate(), excelDO.getOutDate()) < 0) {
                registration.setLeaveOrNot(0);//离场
                registration.setExitTime(excelDO.getOutDate());
                registration.setExitMode(excelDO.getOutType());
                registration.setExitResideAddress(excelDO.getOutAddr());
                if (StringUtils.isNotEmpty(excelDO.getOutAddr())) {
                    List<Map<String, String>> list = splitAddress(excelDO.getOutAddr());
                    if (CollectionUtils.isNotEmpty(list)) {
                        Map<String, String> stringStringMap = list.get(0);
                        registration.setProvince(stringStringMap.get("province"));
                        registration.setCity(stringStringMap.get("city"));
                        registration.setArea(stringStringMap.get("area"));
                        registration.setExitResideAddress(stringStringMap.get("village"));
                    }
                }
            }
            registration.setCommute(convertCommute(excelDO.getCommute()));
            manageUserRegistrationDOList.add(registration);
        }
        return manageUserRegistrationDOList;
    }

    private List<UnitDO> buildUnitList(List<ExcelDO> unitList, ProjectDO projectDO) {
        List<UnitDO> unitDOS = Lists.newArrayList();
        for (ExcelDO excelDO : unitList) {
            UnitDO unitDO = new UnitDO();
            UnitTypeEnum newType = UnitTypeEnum.getNewType(excelDO.getUnitTypeId());
            if (newType != null) {
                unitDO.setProjectId(projectDO.getId());
                unitDO.setUnitType(newType.getNewType());
                unitDO.setUnitDetailName(excelDO.getUnitName());
                unitDO.setUnitName(excelDO.getUnitName());
                unitDO.setOldUnitId(excelDO.getUnitTypeId());
                unitDOS.add(unitDO);
            }

        }
        return unitDOS;
    }

    private String covertJobType(Long personJobId) {
        if (personJobId == 1) {
            return "MANAGER";
        } else if (personJobId == 2) {
            return "WORKER";
        } else if (personJobId == 3) {
            return "SECURITY";
        } else if (personJobId == 4) {
            return "CHEF";
        } else if (personJobId == 5) {
            return "CLEANER";
        } else if (personJobId == 6) {
            return "PURCHASER";
        } else if (personJobId == 7) {
            return "STOWER";
        } else if (personJobId == 8) {
            return "DRIVER";
        }
        return null;
    }

    private Integer convertCommute(String commute) {
        return Objects.equals(commute, "是") ? 1 : 0;
    }

    public static <T> java.util.function.Predicate<T> distinctByKey(java.util.function.Function<? super T, ?> keyExtractor) {
        java.util.Map<Object, Boolean> seen = new java.util.HashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 地址拆分
     * @param address
     * @return
     */
    public static List<Map<String,String>> splitAddress(String address) {
        String regex="(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<village>.*)";
        Matcher m= Pattern.compile(regex).matcher(address);
        String province=null,city=null,area=null,village=null;
        List<Map<String,String>> table=new ArrayList<Map<String,String>>();
        Map<String,String> row=new HashMap<>();
        while(m.find()){
            row=new LinkedHashMap<String,String>();
            province=m.group("province");
            row.put("province", province==null?"":province.trim());
            city=m.group("city");
            row.put("city", city==null?"":city.trim());
            area=m.group("county");
            row.put("area", area==null?"":area.trim());
            village=m.group("village");
            row.put("village", village==null?"":village.trim());
            table.add(row);
        }
        return table;
    }
}
